This notebook works through data taken the night of 2019/01/15 to calibrate the focus offsets between the MMIRS instrument and its two off-axis Shack-Hartmann wavefront sensors. After converging with one of the off-axis WFS's, a pair of images were taken with MMIRS in imaging mode after applying focus changes of +500 and -500 microns at M2. These out-of-focus images can then be analyzed using a curvature wavefront sensing algorithm. We use the system developed for the LSST (https://arxiv.org/abs/1506.04839) to perform the analysis. It is fully generalized and can be configured to work with any telescope/instrument.
In [1]:
# Set up imports, data directory, and configure path to find
import sys
import numpy as np
import matplotlib
matplotlib.use('nbagg')
import matplotlib.pyplot as plt
import astropy.units as u
from astropy import stats
from astropy.io import fits
from mmtwfs.wfs import *
from mmtwfs.zernike import ZernikeVector
from mmtwfs.telescope import MMT
%load_ext autoreload
%autoreload 2
sys.path.append("/Users/tim/src/cwfs/python")
%cd /Users/tim/MMT/mmirs/2019.0115/
from lsst.cwfs.instrument import Instrument
from lsst.cwfs.algorithm import Algorithm
from lsst.cwfs.image import Image, readFile
import lsst.cwfs.plots as plots
In [2]:
# converged with camera 1 to a focus value of 9746.73
# donuts were becoming saturated by even the midpoint of the ramp, but the 3rd readout is fine
cam1_extra_whole = fits.open("tyc3778-00232-1.5988.fits")[3].data # focus 10246.0
cam1_intra_whole = fits.open("tyc3778-00232-1.5989.fits")[3].data # focus 9245.18
cam1_extra = cam1_extra_whole[977-40:977+40, 994-40:994+40] - np.median(cam1_extra_whole)
cam1_intra = cam1_intra_whole[977-40:977+40, 993-40:993+40] - np.median(cam1_intra_whole)
# converved with camera 2 to a focus value of 9695.91
# no saturation even at the end of the ramp
cam2_extra_whole = fits.open("tyc3778-00232-1.5990.fits")[11].data # focus 10195.56
cam2_intra_whole = fits.open("tyc3778-00232-1.5991.fits")[11].data # focus 9194.82
cam2_extra = cam2_extra_whole[981-40:981+40, 992-40:992+40] - np.median(cam2_extra_whole)
cam2_intra = cam2_intra_whole[981-40:981+40, 994-40:994+40] - np.median(cam2_intra_whole)
# write out cutout images for convenience later
fits.writeto("cam1_intra.fits", cam1_intra, overwrite=True)
fits.writeto("cam1_extra.fits", cam1_extra, overwrite=True)
fits.writeto("cam2_intra.fits", cam2_intra, overwrite=True)
fits.writeto("cam2_extra.fits", cam2_extra, overwrite=True)
In [3]:
fig, axs = plt.subplots(2, 2, sharex=True)
axs[0, 0].imshow(cam1_intra, origin='lower')
axs[0, 0].set_title("Camera 1 Intra-focal")
axs[1, 0].imshow(cam1_extra, origin='lower')
axs[1, 0].set_title("Camera 1 Extra-focal")
axs[0, 1].imshow(cam2_intra, origin='lower')
axs[0, 1].set_title("Camera 2 Intra-focal")
axs[1, 1].imshow(cam2_extra, origin='lower')
axs[1, 1].set_title("Camera 2 Extra-focal")
plt.show()
In [5]:
# set up and configure the Instrument instance for doing the CWFS calculation
mmirs = Instrument('mmirs', cam1_intra.shape[0]) # images must be square and same size
mmirs.obscuration = 0.26 # relative size of the central obscuration
mmirs.apertureDiameter = 6.5024 # MMT diameter in meters
mmirs.pixelSize = 18e-6 # MMIRS has 18 micron pixels
mmirs.focalLength = mmirs.apertureDiameter * 2.85 # effective focal length for MMIRS's f/2.85 imaging
mmirs.offset = 2.85**2 / 1.25**2 * .5e-3 # MMIRS images at f/2.85 and we used +/- 500 um focus offsets
algo = Algorithm('exp', mmirs, 3)
In [6]:
fieldXY = [0., 0.] # assume we're on axis. haven't implemented MMT off-axis models into LSST CWFS code yet.
I1_cam1 = Image(readFile("cam1_intra.fits"), fieldXY, Image.INTRA)
I2_cam1 = Image(readFile("cam1_extra.fits"), fieldXY, Image.EXTRA)
algo.runIt(mmirs, I1_cam1, I2_cam1, 'onAxis')
In [7]:
cam1_zv = ZernikeVector()
cam1_zv.from_array(algo.zer4UpNm, modestart=4, normalized=True)
cam1_zv.denormalize()
cam1_zv
Out[7]:
In [8]:
cam1_zv.fringe_bar_chart().show()
plt.show()
In [9]:
plt.imshow(algo.image)
plt.show()
In [10]:
plots.plotImage(algo.Wconverge, "Final wavefront", show=True)
In [11]:
# set up and configure the Instrument instance for doing the CWFS calculation
mmirs = Instrument('mmirs', cam1_intra.shape[0]) # images must be square and same size
mmirs.obscuration = 0.26 # relative size of the central obscuration
mmirs.apertureDiameter = 6.5024 # MMT diameter in meters
mmirs.pixelSize = 18e-6 # MMIRS has 18 micron pixels
mmirs.focalLength = mmirs.apertureDiameter * 2.85 # effective focal length for MMIRS's f/2.85 imaging
mmirs.offset = 2.85**2 / 1.25**2 * .5e-3 # MMIRS images at f/2.85 and we used +/- 500 um focus offsets
algo = Algorithm('exp', mmirs, 3)
In [13]:
fieldXY = [0., 0.] # assume we're on axis. haven't implemented MMT off-axis models into LSST CWFS code yet.
I1_cam2 = Image(readFile("cam2_intra.fits"), fieldXY, Image.INTRA)
I2_cam2 = Image(readFile("cam2_extra.fits"), fieldXY, Image.EXTRA)
algo.runIt(mmirs, I1_cam2, I2_cam2, 'onAxis')
In [ ]: